package com.beiding.v2.grammar;

import com.beiding.v2.base.IContext;
import com.beiding.v2.base.IUnit;
import com.beiding.v2.element.IExpression;
import com.beiding.v2.type.KeywordType;
import com.beiding.v2.type.LogicSymbolType;
import com.beiding.v2.type.OperationSymbolType;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SqlBuilder implements IBuilder {

    private IContext context;

    public void setContext(IContext context) {
        this.context = context;
    }

    private List<IUnit> units = new ArrayList<>();

    public SqlBuilder select() {
        auto(KeywordType.select);
        return this;
    }

    public SqlBuilder select(IUnit... fields) {
        select();
        Collections.addAll(units, fields);
        return this;
    }

    public SqlBuilder from() {
        auto(KeywordType.from);
        return this;
    }

    public SqlBuilder from(IUnit... tables) {
        from();
        Collections.addAll(units, tables);
        return this;
    }

    public SqlBuilder join(IUnit table) {
        auto(KeywordType.join);
        auto(table);
        return this;
    }

    public SqlBuilder on() {
        auto(KeywordType.on);
        return this;
    }

    public SqlBuilder on(ExpressionBuilder expressionBuilder) {
        on();
        handlerExpressionBuilder(expressionBuilder, false);
        return this;
    }


    public SqlBuilder where() {
        auto(KeywordType.where);
        return this;
    }

    public SqlBuilder caze() {
        auto(KeywordType.caze);
        return this;
    }

    public SqlBuilder when() {
        auto(KeywordType.when);
        return this;
    }

    public SqlBuilder then() {
        auto(KeywordType.then);
        return this;
    }


    public SqlBuilder elze() {
        auto(KeywordType.elze);
        return this;
    }

    public SqlBuilder end() {
        auto(KeywordType.end);
        return this;
    }

    public SqlBuilder where(ExpressionBuilder expressionBuilder) {
        where();
        handlerExpressionBuilder(expressionBuilder, false);
        return this;
    }

    public SqlBuilder auto(Object obj) {
        units.add(QueryUtils.auto(obj));
        return this;
    }

    public SqlBuilder eq(Object a, Object b) {
        return twoParameterCompare(a, b, OperationSymbolType.eq);
    }


    public SqlBuilder gt(Object a, Object b) {
        return twoParameterCompare(a, b, OperationSymbolType.gt);
    }

    public SqlBuilder lt(Object a, Object b) {
        return twoParameterCompare(a, b, OperationSymbolType.lt);
    }

    private SqlBuilder twoParameterCompare(Object a, Object b, OperationSymbolType operationSymbolType) {
        auto(a);
        auto(operationSymbolType);
        auto(b);
        return this;
    }


    public SqlBuilder and() {
        return auto(LogicSymbolType.and);
    }

    public SqlBuilder or() {
        return auto(LogicSymbolType.or);
    }

    //在括号内写子句
    public SqlBuilder bracket(ExpressionBuilder obj) {
        return handlerExpressionBuilder(obj, true);
    }

    public SqlBuilder in(Object a, Object... values) {
        auto(a);
        in();
        return values(values);
    }

    public SqlBuilder in() {
        return auto(OperationSymbolType.in);
    }

    public SqlBuilder in(Object a, ExpressionBuilder expressionBuilder) {
        auto(a);
        in();
        return bracket(expressionBuilder);
    }


    private SqlBuilder handlerExpressionBuilder(ExpressionBuilder builder, boolean inner) {
        SqlBuilder sqlBuilder = new SqlBuilder();
        builder.build(sqlBuilder);
        IExpression expression = sqlBuilder.createExpression();
        expression.setInner(inner);
        units.add(expression);
        return this;
    }

    public SqlBuilder values(Object... values) {
        return auto(values);
    }

    //生成表达式
    public IExpression createExpression() {
        return new Expression(units, false);
    }

    public SqlBuilder as(String statement) {
        auto(KeywordType.as);
        units.add(new Statement(statement));
        return this;
    }

    @Override
    public String toString() {
        if (context == null) {
            return "!!!Error:未设置上下文";
        } else {
            return createExpression().build(context);
        }
    }
}
